//
// Created by heqian on 17-8-2.
//

#ifndef AUTOMAHJONG_EDITIMAGE_H
#define AUTOMAHJONG_EDITIMAGE_H

#include "Image.h"
#include "../utils/Prt.h"

using namespace utils;

namespace img {
#define R(val) (val & 0xFF)
#define G(val) ((val >> 8) & 0xFF)
#define B(val) ((val >> 16) & 0xFF)
#define A(val) ((val >> 24) & 0xFF)
//透明算法  c =(1-alpha)* b + alpha*a
#define AB(B, U, A) ((uint8_t)(( ((uint32_t)U << 8) - A * (U - B)) >> 8))
//#define AB(B, U, A) ((uint8_t)(*(mDrawColor + (U << 8) + A) + *(mDrawColor + (B << 8) + ~A))>>8)

//二线插算法 C = A * S + B * (1 - S);
#define ZB(A, B, C, D, X, Y) (uint8_t)((((uint8_t)((A * ((uint16_t) ~X) + B * X) >> 16)) * ((uint16_t) ~Y) + ((uint8_t)((C * ((uint16_t) ~X) + D * X) >> 16)) * Y) >> 16);

    enum RotationAngle {
        Angle_90 = 90,
        Angle_180 = 180,
        Angle_270 = 270,
    };

    class Rect {
    public:
        Rect();

        Rect(Rect *rect);

        Rect(int x, int y, int width, int height);

        int getX() const;

        void setX(int mX);

        int getY() const;

        void setY(int mY);

        int getWidth() const;

        void setWidth(int mWidth);

        int getHeight() const;

        void setHeight(int mHeight);

        Rect &operator=(Rect rect);

    protected:
        int mX, mY, mWidth, mHeight;
    };

    class DrawRect {
    public:
        DrawRect(uint32_t sWidth, uint32_t sHeight, Rect &rect);

        DrawRect(int mSWidth, int mSHeight, int mDX, int mDY, int mDWidth, int mDHeight);

        int getSX() const;

        void setSX(int mSX);

        int getSY() const;

        void setSY(int mSY);

        int getSWidth() const;

        void setSWidth(int mSWidth);

        int getSHeight() const;

        void setSHeight(int mSHeight);

        int getDX() const;

        void setDX(int mDX);

        int getDY() const;

        void setDY(int mDY);

        int getDWidth() const;

        void setDWidth(int mDWidth);

        int getDHeight() const;

        void setDHeight(int mDHeight);

    protected:
        int mSX, mSY, mSWidth, mSHeight;
        int mDX, mDY, mDWidth, mDHeight;

        void init(int sWidth, int sHeight, int dX, int dY, int dWidth, int dHeight);
    };

    class Size {
    public:
        Size(int width, int height);

        int getWidth() const;

        void setWidth(int width);

        int getHeight() const;

        void setHeight(int height);

    protected:
        int mWidth;
        int mHeight;
    };

    class EditImage {
    public:
        EditImage();

        virtual ~EditImage();

        static Prt<EditImage> &get();

        static void setInterface(const Prt<EditImage> &mInterface);

        /**
         * 获得二值化图像
         * @param src 源图像
         * @param value 伐值
         * @return
         */
        virtual Prt<Image> threshold(Prt<Image> &src, uint8_t value);

        /**
         * 获得灰度图像
         * @param src
         * @return
         */
        virtual Prt<Image> gray(Prt<Image> &src);

        /**
        * 获得通道数据
        * @param src
        * @param channe
        * @return
        */
        virtual Prt<Image> channel(Prt<Image> &src, ImageChannel channe);

        /**
         * 合并RGB通道
         * @param r8
         * @param g8
         * @param b8
         * @return
         */
        virtual Prt<Image>
        channelMerge(Prt<Image> &r8, Prt<Image> &g8, Prt<Image> &b8);

        /**
         * 合并RGBA通道
         * @param r8
         * @param g8
         * @param b8
         * @param a8
         * @return
         */
        virtual Prt<Image>
        channelMerge(Prt<Image> &r8, Prt<Image> &g8, Prt<Image> &b8,
                     Prt<Image> &a8);

        /**
         * 转换图像到RGBA8888模式
         * @param src　　源图像
         * @return　返回转换后图像
         */
        virtual Prt<Image> toRGBA_8888(Prt<Image> &src);

        /**
         * 图像反相
         * @param src
         * @return
         */
        virtual Prt<Image> invert(Prt<Image> &src);

        /**
         *裁剪图像
         * @param src　源图像
         * @param rect 　裁剪区域
         * @return 返回裁剪后的图像
         */
        virtual Prt<Image> clip(Prt<Image> &src, Rect &rect);

        /**
         * 裁剪图像
         * @param src  　源图像
         * @param x 裁剪位置　X
         * @param y 裁剪位置　Y
         * @param dWidth 裁剪宽度
         * @param dHeight 裁剪高度
         * @return 返回裁剪后的图像
         */
        virtual Prt<Image> clip(Prt<Image> &src, int x, int y, int dWidth, int dHeight);

        /**
         * 绘制颜色
         * @param src　源图像（被绘制的图像）
         * @param color　绘制颜色
         * @return　是否绘制成功
         */
        virtual bool drawColor(Prt<Image> &src, int color);

        /**
         * 绘制颜色
         * @param src  源图像（被绘制的图像）
         * @param color  绘制颜色
         * @param rect  绘制区域
         * @return  是否绘制成功
         */
        virtual bool drawColor(Prt<Image> &src, int color, Rect &rect);

        /**
         * 填充颜色
         * @param src 源图像（被填充的图像）
         * @param color　填充颜色
         * @return　是否填充成功
         */
        virtual bool fillColor(Prt<Image> &src, int color);

        /**
         * 填充颜色
         * @param src 源图像（被填充的图像）
         * @param color　填充颜色
         * @param rect  填充区域
         * @return　是否填充成功
         */
        virtual bool fillColor(Prt<Image> &src, int color, Rect &rect);

        /**
         * 填充图像
         * @param src 下层
         * @param img 上层图像
         * @param x 起始坐标 X
         * @param y 起始坐标 Y
         * @return
         */
        virtual bool fillImage(Prt<Image> &src, Prt<Image> &img, int x, int y);

        /**
         * 绘制图像
         * @param src 下层
         * @param img 上层图像
         * @param x 起始坐标 X
         * @param y 起始坐标 Y
         * @return
         */
        virtual bool drawImage(Prt<Image> &src, Prt<Image> &img, int x, int y);

        /**
         * 镜像翻转
         * @param src 源图像
         * @param horizontal 是否横向，（true 横向翻转， false 垂直翻转）
         * @return 翻转后的图像
         */
        virtual Prt<Image> mirror(Prt<Image> &src, bool horizontal);

        /**
         * 直角旋转
         * @param src 源图像
         * @param angle 旋转角度
         * @return 旋转后的图像
         */
        virtual Prt<Image> angleRotation(Prt<Image> &src, RotationAngle angle);

        /**
         * 缩放图像 （邻近值算法）
         * @param src 源图像
         * @param width 缩放后的宽度
         * @param height 缩放后的高度
         * @return  缩放后的图像
         */
        virtual Prt<Image> zoomImage_Near(Prt<Image> &src, int width, int height);

        /**
        * 缩放图像 （二次线性插值算法）
        * @param src 源图像
        * @param width 缩放后的宽度
        * @param height 缩放后的高度
        * @return  缩放后的图像
        */
        virtual Prt<Image> zoomImage_BilInear(Prt<Image> &src, int width, int height);

    private:
        static Prt<EditImage> mInterface;
        uint32_t *mGrayColorR;
        uint32_t *mGrayColorG;
        uint32_t *mGrayColorB;
        uint16_t *mDrawColor;
    };

}

#endif //AUTOMAHJONG_EDITIMAGE_H
